<template>
  <div class="app-container">
    <div class="content-container">
   

      <div class="search-container">
        <!-- 左侧参数配置卡片 -->
        <el-card class="query-card">
          <template #header>
            <div class="card-header">
              <span>检索参数配置</span>
            </div>
          </template>
          <div class="page-header">
        <h2 class="page-title">检索测试</h2>
        <p class="page-desc">
          请完成召回测试：确保你的配置可以从数据库召回正确的文本块。如果你调整了这里的默认设置，比如关键词相似度权重，请注意这里的改动不会被自动保存。请务必在聊天助手设置或者召回算子设置处同步更新相关设置。
        </p>
      </div>
          <div class="query-form-container">
            <el-form :model="queryForm" label-width="130px" class="query-form">
              <!-- 相似度阈值 -->
              <el-form-item label="相似度阈值:">
                <el-slider
                  v-model="queryForm.similarity_threshold"
                  :min="0"
                  :max="1"
                  :step="0.01"
                  :format-tooltip="(value) => `${(value * 100).toFixed(0)}%`"
                />
              </el-form-item>

              <!-- 相似度权重 -->
              <el-form-item label="关键字相似度权重:">
                <el-slider
                  v-model="queryForm.vector_similarity_weight"
                  :min="0"
                  :max="1"
                  :step="0.01"
                  :format-tooltip="(value) => `${(value * 100).toFixed(0)}%`"
                />
              </el-form-item>

              <!-- 是否使用图谱 -->
              <el-form-item label="使用知识图谱:">
                <el-switch v-model="queryForm.use_kg" />
              </el-form-item>

              <!-- 问题输入 -->
              <el-form-item label="问题:">
                <el-input
                  v-model="queryForm.question"
                  type="textarea"
                  :rows="8"
                  placeholder="请输入您的问题..."
                />
              </el-form-item>
            </el-form>

            <!-- 底部操作按钮 -->
            <div class="form-actions">
              <el-button
                type="primary"
                @click="handleSearch"
                :loading="searching"
                >测试</el-button
              >
              <el-button @click="resetForm">重置</el-button>
            </div>
          </div>
        </el-card>

        <!-- 右侧检索结果卡片 -->
        <el-card class="result-card" v-loading="searching">
          <template #header>
            <div class="card-header">
              <span>检索结果</span>
              <div class="header-actions" v-if="searchResults.length > 0">
                <el-tooltip content="复制全部结果" placement="top">
                  <el-button type="text" @click="copyResults">
                    <el-icon><CopyDocument /></el-icon>
                  </el-button>
                </el-tooltip>
                <el-tooltip content="导出结果" placement="top">
                  <el-button type="text" @click="handleExport">
                    <el-icon><Download /></el-icon>
                  </el-button>
                </el-tooltip>
              </div>
            </div>
          </template>

          <div class="result-container">
            <div v-if="searchResults.length === 0" class="empty-result">
              <el-empty description="暂无检索结果，请输入问题进行检索" />
            </div>
            <div v-else class="result-list">
              <div
                v-for="(item, index) in searchResults"
                :key="index"
                class="result-item"
              >
                <!-- 相关度指标 -->
                <div class="metrics">
                  <span class="metric">
                    <span class="label">混合相似度</span>
                    <span class="value">{{ item.similarity }}</span>
                  </span>
                  <span class="metric">
                    <span class="label">关键字匹配度</span>
                    <span class="value">{{ item.term_similarity }}</span>
                  </span>
                  <span class="metric">
                    <span class="label">向量相似度</span>
                    <span class="value">{{ item.vector_similarity }}</span>
                  </span>
                </div>

                <!-- JSON内容 -->
                <div class="content-box">
                  <pre class="content-json">{{ item.content }}</pre>
                </div>
              </div>
            </div>

            <!-- 底部分页 -->
            <div class="pagination-container">
              <el-pagination
                v-model:current-page="currentPage"
                v-model:page-size="pageSize"
                :page-sizes="[10, 20, 30, 50]"
                :total="total"
                background
                layout="total, sizes, prev, pager, next, jumper"
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
              />
            </div>
          </div>
        </el-card>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, watch } from "vue";
import { ElMessage, ElLoading } from "element-plus";
import { CopyDocument, Download, Document } from "@element-plus/icons-vue";
import { searchChunk } from "@/api/knowledge/dataset";

// 查询表单参数
const queryForm = reactive({
  dataset_uuids: [],
  document_uuids: [],
  question: "",
  keyword: false,
  topK: 5,
  rerank_id: "",
  similarity_threshold: 0.2,
  use_kg: false,
  vector_similarity_weight: 0.7,
});

// 数据集和文档选项
const datasetOptions = ref([]);
const documentOptions = ref([]);
const modelOptions = ref([
  { value: "model1", label: "BGE-reranker-v1" },
  { value: "model2", label: "BAAI/bge-reranker-large" },
  { value: "model3", label: "自定义模型" },
]);

// 搜索状态和结果
const searching = ref(false);
const testing = ref(false);
const benchmarking = ref(false);
const searchResults = ref([]);

// 分页参数
const currentPage = ref(1);
const pageSize = ref(10);
const total = ref(0);

// 状态参数
const selectedCount = ref(0);
const totalCount = ref(2);

// 监听数据集变化，更新文档选项
watch(
  () => queryForm.dataset_uuids,
  async (newVal) => {
    if (newVal && newVal.length > 0) {
      // 这里应该调用API获取所选数据集的文档列表
      await loadDocuments(newVal);
    } else {
      documentOptions.value = [];
      queryForm.document_uuids = [];
    }
  },
  { immediate: true }
);

// 监听检索方式变化
watch(
  () => queryForm.keyword,
  (isKeyword) => {
    if (!isKeyword) {
      // 如果是语义检索，重置权重为默认值
      queryForm.vector_similarity_weight = 0.5;
    }
  }
);

// 加载数据集列表
async function loadDatasets() {
  // 这里应该调用API获取数据集列表
  try {
    // 模拟API调用
    datasetOptions.value = [
      { value: "10", label: "设备维护知识库" },
      { value: "11", label: "产品说明文档库" },
      { value: "12", label: "技术规范知识库" },
    ];
  } catch (error) {
    console.error("加载数据集失败:", error);
    ElMessage.error("加载数据集失败");
  }
}

// 加载文档列表
async function loadDocuments(datasetIds) {
  // 这里应该调用API获取所选数据集的文档列表
  try {
    // 模拟API调用
    documentOptions.value = [
      { value: "25", label: "设备维护手册.pdf" },
      { value: "27", label: "故障排除指南.docx" },
      { value: "61", label: "质量控制手册.pdf" },
    ];
  } catch (error) {
    console.error("加载文档失败:", error);
    ElMessage.error("加载文档失败");
  }
}

// 执行检索
function handleSearch() {
  const ids = localStorage.getItem("ids");
  let dataset_uuid = "";
  if (ids) {
    const idsObj = JSON.parse(ids);
    dataset_uuid = idsObj.dataset_uuid;
  }
  searching.value = true;
  try {
    searchChunk({
      dataset_uuids: [dataset_uuid],
      // document_uuids: queryForm.document_uuids.length > 0 ? queryForm.document_uuids : undefined,
      question: queryForm.question,
      // keyword: queryForm.keyword,
      // topK: queryForm.topK,
      // rerank_id: queryForm.rerank_id || undefined,
      page: currentPage.value,
      page_size: pageSize.value,
      similarity_threshold: queryForm.similarity_threshold,
      use_kg: queryForm.use_kg,
      vector_similarity_weight: queryForm.vector_similarity_weight,
    }).then((res) => {
      if (res.code == 200) {
        searchResults.value = res.data.chunks
        total.value = res.data.total
      }
    });
  } catch (error) {
    console.error("检索出错:", error);
    ElMessage.error("检索请求失败");
    searchResults.value = [];
  } finally {
    searching.value = false;
  }
}

// 重置表单
function resetForm() {
  queryForm.question = "";
  queryForm.keyword = false;
  queryForm.topK = 5;
  queryForm.similarity_threshold = 0.2;
  queryForm.use_kg = false;
  queryForm.vector_similarity_weight = 0.7;
  queryForm.rerank_id = "";
  // 保留已选数据集和文档
  searchResults.value = [];
}

// 导出结果
function handleExport() {
  if (searchResults.value.length === 0) {
    ElMessage.warning("没有可导出的结果");
    return;
  }

  try {
    // 创建导出数据
    const exportData = searchResults.value.map((item, index) => ({
      序号: index + 1,
      文档: item.document_name || item.source || "未知",
      相似度: `${(item.score * 100).toFixed(2)}%`,
      内容: item.content,
    }));

    // 创建CSV内容
    const csvContent = [
      Object.keys(exportData[0]).join(","), // 表头
      ...exportData.map((row) =>
        Object.values(row)
          .map((value) => `"${String(value).replace(/"/g, '""')}"`)
          .join(",")
      ),
    ].join("\n");

    // 创建Blob对象
    const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });

    // 创建下载链接
    const link = document.createElement("a");
    const url = URL.createObjectURL(blob);

    link.setAttribute("href", url);
    link.setAttribute(
      "download",
      `检索结果_${new Date().toISOString().slice(0, 19).replace(/:/g, "-")}.csv`
    );
    link.style.display = "none";

    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    ElMessage.success("检索结果导出成功");
  } catch (error) {
    console.error("导出失败:", error);
    ElMessage.error("导出失败");
  }
}

// 复制内容
function copyContent(content) {
  if (!content) {
    ElMessage.warning("没有可复制的内容");
    return;
  }

  try {
    navigator.clipboard.writeText(content);
    ElMessage.success("内容已复制到剪贴板");
  } catch (error) {
    console.error("复制失败:", error);
    ElMessage.error("复制失败，请手动选择内容复制");
  }
}

// 复制所有结果
function copyResults() {
  if (searchResults.value.length === 0) {
    ElMessage.warning("没有可复制的结果");
    return;
  }

  try {
    const text = searchResults.value
      .map(
        (item, index) =>
          `结果 ${index + 1} - 相似度: ${(item.score * 100).toFixed(2)}%\n` +
          `来源文档: ${item.document_name || item.source || "未知"}\n` +
          `内容片段:\n${item.content}\n\n`
      )
      .join("---\n");

    navigator.clipboard.writeText(text);
    ElMessage.success("所有结果已复制到剪贴板");
  } catch (error) {
    console.error("复制失败:", error);
    ElMessage.error("复制失败，请手动选择内容复制");
  }
}

// 获取标签类型
function getTagType(type) {
  const typeMap = {
    text: "",
    image: "success",
    table: "warning",
    code: "info",
    pdf: "danger",
  };
  return typeMap[type] || "";
}

// 快速测试
async function runQuickTest() {
  testing.value = true;

  try {
    // 设置快速测试的参数
    const testQuestions = [
      "设备维护的关键步骤是什么？",
      "如何解决传感器故障问题？",
      "质量控制的主要指标有哪些？",
    ];

    const randomQuestion =
      testQuestions[Math.floor(Math.random() * testQuestions.length)];
    queryForm.question = randomQuestion;

    // 执行检索
    await handleSearch();

    ElMessage.success("快速测试完成");
  } catch (error) {
    console.error("快速测试失败:", error);
    ElMessage.error("快速测试失败");
  } finally {
    testing.value = false;
  }
}

// 性能基准测试
async function runBenchmark() {
  if (queryForm.dataset_uuids.length === 0) {
    ElMessage.warning("请至少选择一个数据集");
    return;
  }

  benchmarking.value = true;
  const loadingInstance = ElLoading.service({
    text: "正在进行性能基准测试，请稍候...",
    background: "rgba(0, 0, 0, 0.7)",
  });

  try {
    const testQueries = [
      "设备故障",
      "质量控制",
      "传感器校准",
      "维护计划",
      "故障排除",
      "数据准确性",
    ];

    const results = [];
    const startTime = performance.now();

    // 执行多次查询
    for (const query of testQueries) {
      queryForm.question = query;

      // 执行检索，但不更新UI
      const response = await searchChunk({
        dataset_uuids: queryForm.dataset_uuids,
        document_uuids:
          queryForm.document_uuids.length > 0
            ? queryForm.document_uuids
            : undefined,
        question: query,
        keyword: queryForm.keyword,
        topK: queryForm.topK,
        rerank_id: queryForm.rerank_id || undefined,
        similarity_threshold: queryForm.similarity_threshold,
        use_kg: queryForm.use_kg,
        vector_similarity_weight: queryForm.vector_similarity_weight,
      });

      if (response.code === 200) {
        results.push({
          query,
          resultCount: (response.data || []).length,
          time: response.cost_time || 0,
        });
      }
    }

    const totalTime = performance.now() - startTime;
    const avgTime =
      results.length > 0
        ? results.reduce((sum, item) => sum + item.time, 0) / results.length
        : 0;

    // 展示基准测试结果
    ElMessage({
      message: `基准测试完成：共执行 ${
        results.length
      } 次查询，平均响应时间 ${avgTime.toFixed(2)}ms，总耗时 ${(
        totalTime / 1000
      ).toFixed(2)}s`,
      type: "success",
      duration: 5000,
    });

    // 可以在控制台显示详细结果
    console.table(results);
  } catch (error) {
    console.error("基准测试失败:", error);
    ElMessage.error("基准测试失败");
  } finally {
    benchmarking.value = false;
    loadingInstance.close();
  }
}

// 分页方法
function handleSizeChange(size) {
  pageSize.value = size;
  // 重新获取数据
  handleSearch();
}

function handleCurrentChange(page) {
  currentPage.value = page;
  // 重新获取数据
  handleSearch();
}

onMounted(() => {
  // 初始化页面时加载数据集列表
  loadDatasets();
});
</script>

<style scoped>
/* 修改整体容器背景色为蔚白色 */
.app-container {
  padding: 16px;
  background-color: #f0f2f5; /* 蔚白色(浅灰蓝色)背景 */
  max-height: calc(100vh - 84px);
  display: flex;
  flex-direction: column;
}

.content-container {
  background-color: #fff;
  padding: 20px;
  border-radius: 4px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
  height: 100%;
  overflow: auto;
  display: flex;
  flex-direction: column;
}

.page-header {
  margin-bottom: 20px;
}

.page-title {
  margin: 0 0 8px 0;
  font-size: 22px;
  color: #303133;
}

.page-desc {
  margin: 0;
  color: #606266;
  font-size: 14px;
}

.search-container {
  display: flex;
  gap: 20px;
  flex: 1;
  overflow: hidden;
}

/* 左侧查询卡片 */
.query-card {
  width: 38%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  height: auto; /* 修改为自动高度 */
}

.query-form-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: auto;
  padding: 20px 0;
}

.query-form {
  flex: 1;
}

/* 右侧结果卡片 */
.right-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  position: relative;
}

.result-card {
  flex: 1;
  width: 62%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.result-container {
  flex: 1;
  overflow: auto;
  padding: 10px 0;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.header-actions {
  display: flex;
  gap: 10px;
}

.form-actions {
  display: flex;
  justify-content: center;
  margin-top: 20px;
  gap: 16px;
  padding-bottom: 10px;
}

.empty-result {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 300px;
}

.result-list {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-bottom: 20px;
}

.result-item {
  background-color: #fff; /* 白色背景确保与蔚白色背景区分 */
  border-radius: 4px;
  overflow: hidden;
  border: 1px solid #e8e8e8; /* 淡化边框 */
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03); /* 轻微阴影 */
}

.result-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.result-source {
  font-size: 14px;
  color: #333;
}

.result-content {
  font-size: 14px;
  margin-bottom: 12px;
}

.content-text {
  padding: 12px 16px;
  background-color: #f5f7fa;
  border-radius: 6px;
  border-left: 4px solid #409eff;
  white-space: pre-wrap;
  line-height: 1.6;
  margin-top: 8px;
  font-family: "Source Code Pro", monospace;
}

.result-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 8px;
}

/* 修复el-card的内部结构样式 */
:deep(.el-card__body) {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 0 20px;
}

/* 响应式调整 */
@media (max-width: 1200px) {
  .search-container {
    flex-direction: column;
  }

  .query-card,
  .result-card {
    width: 100%;
    height: auto;
    min-height: 400px;
  }

  .query-card {
    margin-bottom: 20px;
  }
}

/* 状态栏样式 */
.status-bar {
  margin-bottom: 16px;
  display: flex;
  align-items: center;
}

.status-bar .el-tag {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 14px;
  padding: 8px 12px;
  border-radius: 4px;
  background-color: #fff; /* 确保标签背景为白色 */
}

/* 指标区域样式 */
.metrics {
  display: flex;
  padding: 10px 16px;
  border-bottom: 1px solid #f0f0f0;
  background-color: #fafafa; /* 浅灰色背景 */
}

.metric {
  display: flex;
  align-items: center;
  margin-right: 20px;
  font-size: 13px;
}

.label {
  color: #606266;
  margin-right: 5px;
}

.value {
  color: #303133;
  font-weight: bold;
}

/* 内容区域样式 */
.content-box {
  padding: 16px;
  overflow-x: auto;
  background-color: #fff; /* 确保内容区背景为白色 */
}

.content-json {
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;
  font-size: 13px;
  color: #333;
  line-height: 1.5;
}

/* 分页容器样式 */
.pagination-container {
  display: flex;
  justify-content: center;
  margin-top: 16px;
  padding: 16px 0;
  background-color: transparent; /* 透明背景，保持蔚白色背景可见 */
}

/* 确保分页组件在蔚白色背景上清晰可见 */
:deep(.el-pagination) {
  background-color: #fff;
  padding: 8px 16px;
  border-radius: 4px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}
</style>
